package qiyu.live.im.router.provider.service.impl;

import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.qiyu.live.common.interfaces.enums.ImCoreServerIPRedisKey;
import org.qiyu.live.im.constants.AppIdEnums;
import org.qiyu.live.im.dto.ImMsgBody;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.qiyu.live.im.core.server.interfaces.IMRouterHandlerRpc;
import qiyu.live.im.router.provider.service.IMRouterService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sfx
 * Date: 2023-10-12
 * Time: 20:04
 */
@Service
public class IMRouterServiceImpl implements IMRouterService {
    @DubboReference
    private IMRouterHandlerRpc imRouterHandlerRpc;

    @Resource
    private StringRedisTemplate redisTemplate;

    /**
     * 这里router层只起到一个转发的作用,转发到im-core-server上
     *
     * @param imMsgBody 用户信息
     */
    @Override
    public boolean sendMsg(ImMsgBody imMsgBody) {
        String ip = redisTemplate.opsForValue().
                get(ImCoreServerIPRedisKey.ImCoreServerIp + imMsgBody.getAppId() + ":" + imMsgBody.getUserId());
        assert ip != null;
        ip = ip.substring(0, ip.indexOf("%"));
        if (StrUtil.isEmpty(ip)) {
            return false;
        }
        RpcContext.getContext().set("ip", ip);
        imRouterHandlerRpc.onReceive(imMsgBody);
        return true;
    }

    @Override
    public boolean batchSendMsg(List<ImMsgBody> imMsgBodyList) {
        // 我们这里进行一次优化,按照Ip分类,分成多批次的ImMsgBody发送出去
        // 1. 得到所有ip的cacheKey
        // 1.1 得到所有的userId
        List<Long> userIds = imMsgBodyList.stream().map(ImMsgBody::getUserId).toList();
        List<String> ipCacheKeys = new ArrayList<>();
        userIds.forEach(userId -> {
            String cacheKey = ImCoreServerIPRedisKey.ImCoreServerIp + AppIdEnums.QIYU_LIVE_BIZ.getCode() + ":" + userId;
            ipCacheKeys.add(cacheKey);
        });

        // userId->ImMsgBody,能够根据userId查询出ImMsgBody
        Map<Long, ImMsgBody> imMsgBodyMap = imMsgBodyList.stream().collect(Collectors.toMap(ImMsgBody::getUserId, x -> x));

        // 2. 分批次查询出所有的ip
        List<String> ips = redisTemplate.opsForValue().multiGet(ipCacheKeys);

        // 3. 根据ip查询出对应的一组userId,使用一个map做映射
        Map<String, List<Long>> map = new HashMap<>();
        assert ips != null;
        ips.forEach(ip -> {
            String currentIp = ip.substring(0, ip.indexOf("%"));
            Long userId = Long.valueOf(ip.substring(ip.indexOf("%") + 1));
            map.computeIfAbsent(currentIp, x -> new ArrayList<>()).add(userId);
        });

        // 4. 遍历Map集合,批量的发送一组ImMsgBody
        for (String ip : map.keySet()) {
            // Dubbo的SPI机制去定位到具体的Im-core-server机器
            RpcContext.getContext().set("ip", ip);
            List<Long> ids = map.get(ip);
            List<ImMsgBody> imMsgBodies = new ArrayList<>();
            ids.forEach(userId -> {
                imMsgBodies.add(imMsgBodyMap.get(userId));
            });
            imRouterHandlerRpc.batchOnReceive(imMsgBodies);
        }
        return false;
    }
}